package com.atguigu.tingshu.user.service.impl;

import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.service.UserPaidTrackService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.LocalDate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private UserPaidTrackService userPaidTrackService;

    @Autowired
    private KafkaService kafkaService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        this.updateUserPaidRecord(userPaidRecordVo);
    }

    @Override
    public void sendMsgToUser(long userId) {
        System.out.println(userId+":\t vip 还有一天即将过期，请续费");
    }

    @Override
    public void updateVipExpireStatus() {
        //  提前通知用户vip 到期！

        //  查询到当前哪些是需要更新的用户信息. 【is_vip = 1; vip_expire_time>new Date();  vip_expire_time<new Date();】
        //  当前系统时间
                Date currentTime = new Date();
        //        //  Date date = new LocalDate(currentTime).minusDays(1).toDate();
        //        Date date = new LocalDate(currentTime).plusDays(1).toDate();
        //
        //        LambdaQueryWrapper<UserInfo> wrapper1 = new LambdaQueryWrapper<>();
        //        //  16号到期：应该15号通知   getVipExpireTime=16号： date+1 注意年月日时分秒:
        //        wrapper1.eq(UserInfo::getIsVip,1).eq(UserInfo::getVipExpireTime,date);
        //        //  提前一天到期的vip用户集合列表.
        //        List<UserInfo> userInfoExpireList = userInfoMapper.selectList(wrapper1);
        //        if (!CollectionUtils.isEmpty(userInfoExpireList)){
        //            userInfoExpireList.forEach(userInfo -> {
        //                //  发送消息
        //                kafkaService.sendMsg("user.vip.expire.time",userInfo.getId().toString());
        //            });
        //        }

        //  查询哪些vip 是过期状态
        //  构建查询条件
        LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserInfo::getIsVip,1).lt(UserInfo::getVipExpireTime,currentTime);


        List<UserInfo> userInfoList = userInfoMapper.selectList(wrapper);
        //  判断
        if (!CollectionUtils.isEmpty(userInfoList)){
            //  修改用户状态.
            userInfoList.forEach(userInfo -> {
                //  修改为非vip 状态.
                userInfo.setIsVip(0);
                //  userInfoMapper.updateById(userInfo);
            });
            this.updateBatchById(userInfoList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserPaidRecord(UserPaidRecordVo userPaidRecordVo) {
        try {
            //  根据itemType 判断用户使用余额购买的什么商品  一次只购买1个专辑
            if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)){
                //  购买的专辑. user_paid_album
                //  防止重复添加可以先判断当前表中是否有当前订单数据
                Long count = userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo()));
                //  表中已存在
                if (count>0){
                    return;
                }
                //  声明对象
                UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
                //  赋值
                userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
                //  专辑Id
                userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
                //  保存数据
                userPaidAlbumMapper.insert(userPaidAlbum);

            }else if(userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)){
                //  购买声音. user_paid_track   购买很多集声音.
                //  防止重复添加
                Long count = userPaidTrackMapper.selectCount(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo()));
                //  表中已存在
                if (count>0){
                    return;
                }

                //  获取专辑Id 可以根据声音Id 获取声音对象。声音对象中有专辑Id
                //  声音Id 包含很多集，但是每一集对应的专辑Id都是一样的！
                Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0));
                Assert.notNull(trackInfoResult,"返回声音集合为空");
                TrackInfo trackInfo = trackInfoResult.getData();
                Assert.notNull(trackInfo,"声音对象为空");
                //  循环遍历声音集数.
                //            for (Long trackId : userPaidRecordVo.getItemIdList()) {
                //                //  创建一个对象
                //                UserPaidTrack userPaidTrack = new UserPaidTrack();
                //                //  赋值：
                //                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
                //                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
                //                //  赋值专辑Id
                //                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
                //                userPaidTrack.setTrackId(trackId);
                //                //  保存
                //                userPaidTrackMapper.insert(userPaidTrack);
                //            }
                //  批量保存
                List<UserPaidTrack> userPaidTrackList = userPaidRecordVo.getItemIdList().stream().map(trackId -> {
                    //  创建一个对象
                    UserPaidTrack userPaidTrack = new UserPaidTrack();
                    //  赋值：
                    userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
                    userPaidTrack.setUserId(userPaidRecordVo.getUserId());
                    //  赋值专辑Id
                    userPaidTrack.setAlbumId(trackInfo.getAlbumId());
                    userPaidTrack.setTrackId(trackId);
                    return userPaidTrack;
                }).collect(Collectors.toList());
                //  批量保存
                userPaidTrackService.saveBatch(userPaidTrackList);

            } else {
                //  防止重复添加
                Long count = userVipServiceMapper.selectCount(new LambdaQueryWrapper<UserVipService>().eq(UserVipService::getOrderNo, userPaidRecordVo.getOrderNo()));
                //  表中已存在
                if (count>0){
                    return;
                }
                //  购买vip. user_vip_service
                //  vip_service_config.id {1,2,3}
                Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
                //  根据 服务配置Id查询 配置项
                VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
                //  vipServiceConfig.getServiceMonth() 购买的时长：
                //  第一次购买 1个月： 当前系统时间+购买时长
                //  Instant instant = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
                //  new Date(); 阿里巴巴开发手册上说了，日期加减
                //  Calendar calendar = Calendar.getInstance();
                //  calendar.add(Calendar.MONTH,vipServiceConfig.getServiceMonth());
                //  Date time = calendar.getTime();

                //  第二次购买 ，在第一次未过期之前购买： vip 续期：第一次购买的过期时间+本次购买的时间
                //  获取当前系统时间：
                //            Instant instant = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
                //            Date startTime = Date.from(instant);
                //  系统时间
                Date startTime = new Date();
                //  判断是否有续期需求
                //  先获取到当前用户信息.
                UserInfo userInfo = this.getById(userPaidRecordVo.getUserId());
                //  is_vip = 1 说是会员  xxl-job: 定时任务调度框架.
                if (null != userInfo && userInfo.getIsVip().intValue() == 1 && userInfo.getVipExpireTime().after(new Date())){
                    //  需要获取到当前过期时间
                    startTime = userInfo.getVipExpireTime();
                }
                //  时间相加
                Date expireTime = new LocalDate(startTime).plusMonths(vipServiceConfig.getServiceMonth()).toDate();
                //  创建对象
                UserVipService userVipService = new UserVipService();
                //  赋值：
                userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
                userVipService.setUserId(userPaidRecordVo.getUserId());
                //  开始时间
                userVipService.setStartTime(new Date());
                //  过期时间：看你购买的服务器配置信息.
                userVipService.setExpireTime(expireTime);
                //  保存数据
                userVipServiceMapper.insert(userVipService);

                //  修改你的身份象征：user_info.is_vip=1
                userInfo.setIsVip(1);
                userInfo.setVipExpireTime(expireTime);

                int i = 1/0;
                //  如果用户信息存储到缓存了。那么这个地方不但要更新数据库，还需要更新缓存redis.  延迟双删！
                //  修改用户为vip同时更新vip的过期时间.
                this.updateById(userInfo);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
        //  select * from user_paid_track where user_id=? and album_id = ?;
        return userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId,userId).eq(UserPaidTrack::getAlbumId,albumId)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
    }

    @Override
    public Boolean isPaidAlbum(Long albumId, Long userId) {
        //  查询数据 select * from user_paid_album where user_id = ? and album_id = ?;
        return userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId,userId).eq(UserPaidAlbum::getAlbumId,albumId))==null?false:true;
    }

    /**
     * @param albumId     专辑Id
     * @param trackIdList 需要付费的声音Id集合
     * @param userId      用户Id
     * @return
     */
    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {
        //	1. 判断用户是否购买过专辑.user_paid_album
        LambdaQueryWrapper<UserPaidAlbum> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId);
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(wrapper);

        //	判断这个专辑是否为空.
        if (null != userPaidAlbum) {
            //	创建一个map 集合;
            Map<Long, Integer> map = new HashMap<>();
            //	说明当前这个用户购买过这个专辑.
            for (Long trackId : trackIdList) {
                //	买过声音，那么声音的标识 1
                map.put(trackId, 1);
            }
            //	返回数据
            return map;
        } else {
            //	查询这个用户购买的声音Id集合列表
            //	select * from  user_paid_track where user_id = ? and album_id = ?;
            LambdaQueryWrapper<UserPaidTrack> wrapper1 = new LambdaQueryWrapper<>();
            //	按照专辑Id 查询
            //	wrapper1.eq(UserPaidTrack::getUserId,userId).eq(UserPaidTrack::getAlbumId,albumId);
            //	按照声音Id 查询
            wrapper1.eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, trackIdList);
            List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper1);
            //	进行转换. 用户买过的声音Id列表
            List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            //	创建一个map 集合;
            Map<Long, Integer> map = new HashMap<>();
            //	需要判断： trackIdList
            for (Long trackId : trackIdList) {
                //	用户购买过这个声音Id
                if (userPaidTrackIdList.contains(trackId)) {
                    //	买过声音，那么声音的标识 1
                    map.put(trackId, 1);
                } else {
                    //	没有买过声音，那么声音的标识 1
                    map.put(trackId, 0);
                }
            }
            return map;
        }
    }

    @Override
    public UserInfoVo getUserInfoById(Long userId) {
        //	创建对象
        UserInfoVo userInfoVo = new UserInfoVo();
        //	获取用户信息
        UserInfo userInfo = this.getById(userId);
        //	属性拷贝：
        BeanUtils.copyProperties(userInfo, userInfoVo);
        //	返回数据
        return userInfoVo;
    }
}
